#include <QRegularExpression>
#include <QSet>
#include <common/pinyinconverter.h>
#include <common/logger/logger.h>
#include "nameconverter_p.h"

NameInfo NameConverterPrivate::cvt2NameInfo(const QString& name, Ethnicity ethnicity)
{
	//检验姓名合法性
	if (!validateName(name))
	{
		return {};
	}

	//获取转换规则
	const auto& function = getNamingRuleByEthnicity(ethnicity);

	if (!function)
	{
		LOG_ERROR("function 回调函数为空");
		return {};
	}

	//获得pair结果
	const QPair<QString, QString>& pair = function(name);

	//检验名是否为空
	if (!pair.second.isEmpty())
		return constructNameInfo(pair.first, pair.second);

	return {};
}

bool NameConverterPrivate::validateName(const QString& text)
{
	// 检查空字符串
	if (text.isEmpty())
	{
		LOG_ERROR("姓名字符串为空");
		return false;
	}

	// 去除首尾空格
	QString trimmedName = text.trimmed();
	if (trimmedName.isEmpty())
	{
		LOG_ERROR("姓名字符串为空");
		return false;
	}

	// 检查长度,当为姓名的时候，保证长度大于等于2
	if (trimmedName.length() < 2)
	{
		LOG_ERROR("姓名长度小于最低要求长度");
		return false;
	}

	// 确保不以分隔符开头或结尾
	if (trimmedName.startsWith("·") || trimmedName.endsWith("·"))
	{
		LOG_ERROR("以特殊的命名分隔符'·'开头或结尾,姓名格式有误");
		return false;
	}

	//确保没有连续的分隔符
	if (trimmedName.contains("··"))
	{
		LOG_ERROR("姓名中含有连续的姓名分隔符'·',姓名格式有误");
		return false;
	}

	// 检查是否全部为中文字符，允许有·
	static const QRegularExpression nameRegex(QStringLiteral("^[\\x{4e00}-\\x{9fa5}·]+$"));
	if (!nameRegex.match(trimmedName).hasMatch())
	{
		LOG_ERROR("姓名中含有除中文和'·'以外的特殊符号");
		return false;
	}

	return true;
}

NameParser NameConverterPrivate::getNamingRuleByEthnicity(Ethnicity ethnicity)
{
	static const QMap<Ethnicity, NameParser> k_Ethnicity2NamingRule = {
			// 采用 [姓氏 + 名字] 结构的民族（姓在前，名在后）- 使用 parseHanStyleName
			// 这些民族通常不使用点号，或点号不是命名规则的一部分
			{Ethnicity::HAN, parseHanStyleName},
			{Ethnicity::HUI, parseHanStyleName},
			{Ethnicity::MIAO, parseHanStyleName},
			{Ethnicity::ZHUANG, parseHanStyleName},
			{Ethnicity::BUYEI, parseHanStyleName},
			{Ethnicity::KOREAN, parseHanStyleName},
			{Ethnicity::DONG, parseHanStyleName},
			{Ethnicity::YAO, parseHanStyleName},
			{Ethnicity::BAI, parseHanStyleName},
			{Ethnicity::TUJIA, parseHanStyleName},
			{Ethnicity::LI, parseHanStyleName},
			{Ethnicity::LISU, parseHanStyleName},
			{Ethnicity::SHE, parseHanStyleName},
			{Ethnicity::GAOSHAN, parseHanStyleName},
			{Ethnicity::LAHU, parseHanStyleName},
			{Ethnicity::SUI, parseHanStyleName},
			{Ethnicity::DONGXIANG, parseHanStyleName},
			{Ethnicity::NAXI, parseHanStyleName},
			{Ethnicity::JINGPO, parseHanStyleName},
			{Ethnicity::TU, parseHanStyleName},
			{Ethnicity::MULAO, parseHanStyleName},
			{Ethnicity::QIANG, parseHanStyleName},
			{Ethnicity::BLANG, parseHanStyleName},
			{Ethnicity::SALAR, parseHanStyleName},
			{Ethnicity::MAONAN, parseHanStyleName},
			{Ethnicity::GELAO, parseHanStyleName},
			{Ethnicity::XIBE, parseHanStyleName},
			{Ethnicity::ACHANG, parseHanStyleName},
			{Ethnicity::PUMI, parseHanStyleName},
			{Ethnicity::NU, parseHanStyleName},
			{Ethnicity::DEANG, parseHanStyleName},
			{Ethnicity::BONAN, parseHanStyleName},
			{Ethnicity::YUGUR, parseHanStyleName},
			{Ethnicity::GIN, parseHanStyleName},
			{Ethnicity::JINO, parseHanStyleName},
			{Ethnicity::HEZHEN, parseHanStyleName},

			// 可能使用点号的汉式命名民族 - 使用 parsePrefixMayWithDot
			{Ethnicity::MONGOL, parsePrefixMayWithDot},// 蒙古族可能有复姓带点
			{Ethnicity::YI, parsePrefixMayWithDot},    // 彝族可能有父子连名带点
			{Ethnicity::MAN, parsePrefixMayWithDot},   // 满族可能有复姓带点
			{Ethnicity::HANI, parsePrefixMayWithDot},  // 哈尼族可能有父子连名带点
			{Ethnicity::DAI, parsePrefixMayWithDot},   // 傣族可能有贵族姓氏带点
			{Ethnicity::VA, parsePrefixMayWithDot},    // 佤族可能有父子连名带点
			{Ethnicity::DAUR, parsePrefixMayWithDot},  // 达斡尔族可能有复姓带点
			{Ethnicity::EVENKI, parsePrefixMayWithDot},// 鄂温克族可能有氏族名带点
			{Ethnicity::OROQEN, parsePrefixMayWithDot},// 鄂伦春族可能有氏族名带点

			// 采用 [本名 + 父名] 结构的民族（名前"姓"后）- 使用 parseLastNameWithDot
			{Ethnicity::UYGHUR, parseLastNameWithDot},
			{Ethnicity::KAZAK, parseLastNameWithDot},
			{Ethnicity::KIRGIZ, parseLastNameWithDot},
			{Ethnicity::TAJIK, parseLastNameWithDot},
			{Ethnicity::UZBEK, parseLastNameWithDot},
			{Ethnicity::TATAR, parseLastNameWithDot},

			// 传统上 [只有名] 的民族（无姓氏）- 使用 parseAllNameStyle
			{Ethnicity::TIBETAN, parseAllNameStyle},
			{Ethnicity::MONBA, parseAllNameStyle},
			{Ethnicity::LHOBA, parseAllNameStyle},

			// 其他特殊规则民族
			{Ethnicity::RUSSIAN, parseSpecial},    // 俄罗斯族
			{Ethnicity::DERUNG, parsePrefixWithDot}// 独龙族
	};

	return k_Ethnicity2NamingRule.value(ethnicity, parseHanStyleName);
}

QString NameConverterPrivate::parseFirstCell(const QString& fieldName, const PinyinConverter& pinyinConverter)
{
	// 此处如果姓名中有"·"符号，导出的首拼会乱码，需单独处理 p？y
	// 分别处理每个姓名部分，再用·拼接；导出效果 p·y
	QString personalFirst;
	if (fieldName.contains("·"))
	{
		QStringList nameParts = fieldName.split("·");
		QStringList firstLetters;

		// 获取每个部分的首字母
		std::transform(nameParts.begin(), nameParts.end(),
					   std::back_inserter(firstLetters),
					   [&pinyinConverter](const QString& part) {
						   return pinyinConverter.cvt2FirstCell(part);
					   });

		// 用"·"连接所有首字母
		personalFirst = std::accumulate(
				firstLetters.begin(), firstLetters.end(), QString(""),
				[](const QString& result, const QString& letter) {
					return result.isEmpty() ? letter : result + "·" + letter;
				});
	}
	else
	{
		// 没有"·"符号的直接调用拼音转换器
		personalFirst = pinyinConverter.cvt2FirstCell(fieldName);
	}
	return personalFirst;
}
NameInfo NameConverterPrivate::constructNameInfo(const QString& surname, const QString& personalName)
{
	// 获取拼音转换器实例
	auto& pinyinConverter = PinyinConverter::instance();
	NameInfo info;
	// 设置姓和名
	info.surName = surname;
	info.personalName = personalName;

	// 处理姓的拼音
	if (!surname.isEmpty())
	{
		info.surnameSpl = pinyinConverter.cvt2Pinyin(surname);
		info.surNameFspl = parseFirstCell(surname, pinyinConverter);
	}

	// 处理名的拼音
	info.personalNameSpl = pinyinConverter.cvt2Pinyin(personalName);
	info.personalNameFspl = parseFirstCell(personalName, pinyinConverter);

	return info;
}

QPair<QString, QString> NameConverterPrivate::parseHanStyleName(const QString& name)
{
	static const QSet<QString> k_CompoundSurnames = {
			"欧阳", "上官", "皇甫", "令狐", "诸葛", "司徒", "司马", "夏侯", "尉迟",
			"申屠", "慕容", "长孙", "宇文", "东方", "独孤", "端木", "南宫", "万俟",
			"闻人", "公羊", "赫连", "澹台", "宗政", "濮阳", "公冶", "太叔", "仲孙",
			"钟离", "鲜于", "司空", "闾丘", "亓官", "司寇", "巫马", "公西", "颛孙",
			"壤驷", "公良", "漆雕", "乐正", "宰父", "谷梁", "拓跋", "夹谷", "轩辕",
			"段干", "百里", "呼延", "东郭", "南门", "羊舌", "微生", "梁丘", "左丘",
			"东门", "第五", "公户", "公玉", "公仪", "公仲", "公上", "公门", "公山",
			"公坚", "公伯", "西门", "公祖", "公乘", "贯丘", "公皙", "南荣", "东里",
			"东宫", "仲长", "子书", "子桑", "即墨", "达奚", "褚师", "吴铭", "公输"};

	QString surname;
	QString personalName;

	// 尝试匹配复姓
	if (name.length() >= 2)
	{
		QString potentialCompound = name.left(2);
		if (k_CompoundSurnames.contains(potentialCompound))
		{
			surname = potentialCompound;
			personalName = name.mid(2);
		}
	}
	// 如果不是复姓，则取第一个字符作为姓
	if (surname.isEmpty())
	{
		surname = name.left(1);
		personalName = name.mid(1);
	}
	return qMakePair(surname, personalName);
}

QPair<QString, QString> NameConverterPrivate::parseLastNameWithDot(const QString& name)
{
	// 实现姓后置解析逻辑
	// 例如：玛丽亚·伊万诺娃 (名: 玛丽亚, 姓: 伊万诺娃)
	//艾力・买买提・阿不都 (名: 艾力, 姓: 买买提・阿不都)
	QStringList parts = name.split("·");
	if (parts.size() >= 2)
	{
		QString surname = parts.mid(1, parts.size() - 1).join("·");
		QString personalName = parts.first();// 合并前n-1段为名
		return {surname, personalName};
	}
	LOG_WARN(QString("%0解析失败，返回为空").arg(name));
	return {};
}

QPair<QString, QString> NameConverterPrivate::parsePrefixWithDot(const QString& name)
{
	// 孔当·迪 ==> 姓:孔当   名：迪
	QStringList split = name.split("·");
	if (!split.isEmpty() && split.size() == 2)
	{
		return qMakePair(QString(split.first()), QString(split.last()));
	}
	LOG_WARN(QString("%0解析失败，返回为空").arg(name));
	return {};
}

QPair<QString, QString> NameConverterPrivate::parsePrefixMayWithDot(const QString& name)
{
	if (name.contains(("·")))
	{
		return parsePrefixWithDot(name);
	}
	return parseHanStyleName(name);
}

QPair<QString, QString> NameConverterPrivate::parseAllNameStyle(const QString& name)
{
	//扎西多吉  名: 扎西多吉
	return qMakePair(QString(), name);
}

QPair<QString, QString> NameConverterPrivate::parseSpecial(const QString& name)
{
	//伊万·伊万诺维奇·伊万诺夫==> 姓:伊万诺夫  名：伊万
	QStringList split = name.split("·");
	if (!split.isEmpty() && split.size() >= 2)
	{
		return qMakePair(QString(split.last()), QString(split.first()));
	}
	LOG_WARN(QString("%0解析失败，返回为空").arg(name));
	return {};
}
